package thulearningcore;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Observable;
import java.util.Observer;

import thulearningcore.util.TLDownloader;
import thulearningcore.util.TLNullConverter;

public class CourseFile extends CourseDetailInfo implements Cloneable {

	private String layerID;

	private int id;
	private String fileSize;
	private String fileURL;
	private String postDate;

	private String fullName;
	private String MIMEType;

	// Download state will not be saved
	private int downloadState;
	private TLDownloader downloader;

	public static final String HOMEWORK_FLAG = "HMWK";
	protected static final String defaultURL = LearningManager.getBaseAddress();// "http://learn.tsinghua.edu.cn";

	public CourseFile() {
		this(null, null, null, null, 0, null, null, null);
	}

	public CourseFile(String courseID, String layerID, String title,
			String fileURL, int id, String detail, String fileSize,
			String postDate) {
		super(courseID, title, null);

		this.layerID = layerID;

		this.id = id;
		this.detail = detail;
		this.postDate = postDate;
		this.fileSize = fileSize;
		this.fileURL = fileURL;
		this.fullName = null;

		this.downloadState = TLDownloader.NOT_START;
	}

	public static CourseFile parseCourseFile(CourseHomework hw) {
		if (!hw.isFileExist())
			return null;

		String title = hw.getDetailFileTitle();
		//
		CourseFile cf = new CourseFile(hw.getCourseID(), HOMEWORK_FLAG,
				title, hw.getDetailFileURL(),
				hw.getDetailFileId(), "", "", "");
		return cf;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public void setLayerID(String layerID) {
		this.layerID = layerID;
	}

	public String getLayerID() {
		return layerID;
	}

	public String getPostDate() {
		return postDate;
	}

	public void setPostDate(String postDate) {
		this.postDate = postDate;
	}

	public String getFileSize() {
		return fileSize;
	}

	public void setFileSize(String fileSize) {
		this.fileSize = fileSize;
	}

	public String getFileURL() {
		return baseURL + fileURL;
	}

	public void setFileURL(String fileURL) {
		this.fileURL = fileURL;
	}

	public int getDownloadState() {
		return downloadState;
	}

	public TLDownloader getDownloader() {
		return downloader;
	}

	public TLDownloader downloadFile(String path) {
		return this.downloadFile(path, this.getDefaultFileName());
	}

	public TLDownloader downloadFile(String path, String filename) {
		try {

			// String fullName = TLURLConnection.download(defaultURL
			// + this.fileURL, path, filename);
			// this.setFullName(fullName);
			if (null != downloader
					&& TLDownloader.DOWNLOADING == downloader.getState()) {
				return downloader;
			}

			downloader = new TLDownloader(new URL(this.getFileURL()), path,
					filename);
			downloader.addObserver(new Observer() {
				@Override
				public void update(Observable o, Object arg) {
					// TODO Auto-generated method stub
					TLDownloader downloader = CourseFile.this.downloader;
					if (null == downloader) {
						return;
					}

					CourseFile.this.downloadState = downloader.getState();
					if (downloader.getState() == TLDownloader.COMPLETE) {
						CourseFile.this.fullName = downloader.getFullName();
						CourseFile.this.MIMEType = downloader.getMIMEType();
					}
				}
			});
			downloader.download();
			return downloader;

		} catch (Exception e) {
			// TODO Auto-generated catch block
			return null;
		}
	}

	public void setFullName(String fullName) {
		this.fullName = fullName;
	}

	public void setMIMEType(String MIMEType) {
		this.MIMEType = MIMEType;
	}

	public String getFullName() {
		return this.fullName;
	}

	public String getMIMEType() {
		return this.MIMEType;
	}

	public String getDefaultFileName() {
		return this.courseID + "_" + this.layerID + "_" + this.id + "_"
				+ this.title.hashCode();
	}

	@Override
	synchronized protected boolean checkUpdate(
			ArrayList<? extends CourseDetailInfo> cache) {
		// TODO Auto-generated method stub
		if (!(this.updated |= !cache.contains(this))) {
			CourseFile c = (CourseFile) cache.get(cache.indexOf(this));
			if (null != c) {
				this.updated |= c.isUpdated();
			}
		}
		return this.updated;
	}

	public void writeData(DataOutputStream dos) throws IOException {
		super.writeData(dos);

		dos.writeUTF(TLNullConverter.convert(this.layerID));

		dos.writeInt(this.id);
		dos.writeUTF(TLNullConverter.convert(this.fileSize));
		dos.writeUTF(TLNullConverter.convert(this.fileURL));
		dos.writeUTF(TLNullConverter.convert(this.postDate));
		dos.writeUTF(TLNullConverter.convert(this.fullName));
		dos.writeUTF(TLNullConverter.convert(this.MIMEType));
	}

	@Override
	public CourseFile readData(DataInputStream dis) throws IOException {
		super.readData(dis);

		this.layerID = TLNullConverter.revert(dis.readUTF());

		this.id = dis.readInt();
		this.fileSize = TLNullConverter.revert(dis.readUTF());
		this.fileURL = TLNullConverter.revert(dis.readUTF());
		this.postDate = TLNullConverter.revert(dis.readUTF());
		this.fullName = TLNullConverter.revert(dis.readUTF());
		this.MIMEType = TLNullConverter.revert(dis.readUTF());

		return this;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = super.hashCode();
		result = prime * result
				+ ((fileSize == null) ? 0 : fileSize.hashCode());
		result = prime * result + ((fileURL == null) ? 0 : fileURL.hashCode());
		result = prime * result + id;
		result = prime * result + ((layerID == null) ? 0 : layerID.hashCode());
		result = prime * result
				+ ((postDate == null) ? 0 : postDate.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (!super.equals(obj))
			return false;
		if (getClass() != obj.getClass())
			return false;
		CourseFile other = (CourseFile) obj;
		if (fileSize == null) {
			if (other.fileSize != null)
				return false;
		} else if (!fileSize.equals(other.fileSize))
			return false;
		if (fileURL == null) {
			if (other.fileURL != null)
				return false;
		} else if (!fileURL.equals(other.fileURL))
			return false;
		if (postDate == null) {
			if (other.postDate != null)
				return false;
		} else if (!postDate.equals(other.postDate))
			return false;
		return true;
	}

	public CourseFile clone() throws CloneNotSupportedException {
		CourseFile cf = (CourseFile) super.clone();
		cf.downloader = null;
		cf.downloadState = TLDownloader.NOT_START;
		return cf;
	}
}
